import React, { useRef, useState, useEffect } from 'react';
import { Modal, Table, Button, Upload, message, Popconfirm, Progress } from 'antd';
import { ClosecircleBlack, CheckcircleBlack } from '@/components/el/ElIcon';
import { ElNotification } from '@/components/el';
import './index.less';
import iconAdd from './img/Icon-add.svg';
import iconDownload from './img/Icon-download.svg';
import iconDel from './img/Icon-dele.svg';
import { commonExport } from '@/utils/utils';
import { omit, divide } from 'ramda';
import { getModalFooter } from './config';
import { fetchImportRate } from './service';

/**
 * @name ELImportExcel
 * # ELImportExcel 使用文档

注意: ELImportExcel 基础antd  Modal/Table/Upload组件组合而成，一次只能选择一个文件，调用接口成功后会返回信息。/把文件给后端。后端解析返回给前端

## 使用例子

```javascript
import { ELImportExcel } from '@/components/el';

  imports = () => {
    console.log('导入');
    const { importModalRef } = this.state;
    importModalRef.openModal();
    //importModalRef.closeModal();
  };
    //获取modalref
  modalRef = (importModalRef) => {
    this.setState({
      importModalRef
    });
  };
  //导入接口调用成功后的回调
  importCallBack = (rep) => {
    console.log('reprep', rep);
  };

  <ELImport_3
            push={push}
            prefix='/yst-system'
            templateCode='yst_system_user_import'
            downTemplateConfig={{
              mode: 'templateCode',
              fileName: '系统用户导入模板',
            }}
            importConfig={{
              mode: 'templateCode',
              maxSize: 20,
              sizeUnit: 'MB',
              note: '仅支持xlsx文件，不能大于20mb',
              accept: 'xlsx|xls|xlsx'
            }}
            onRef={this.importModalRef}
          />

```

##修改记录
- 2021-06-18: 增加关闭弹出框后清除已选择的文件功能
 */

const constPrefixStr =
  process.env.NODE_ENV !== 'development'
    ? window.location.port
    : `:${window.location.port}`;
interface Props {
  push: any;
  templateCode?: string;
  prefix: string;//域前缀
  downTemplateConfig: {
    mode: 'templateCode' | 'request' | 'path';//下载模式
    url?: string;//非templateCode模式下必填，下载路径
    requestMethod?: string;
    fileName: string;//下载文件重保存文件名
  }
  importConfig: {
    mode: 'templateCode' | 'request';//上传模式
    url?: string;//非templateCode模式下必填，上传路径
    onSuccess?: Function; //请求成功回调
    onFailed?: Function;//请求失败回调
    accept: string; //上传文件类型，校验
    maxSize: number; //文件最大大小
    sizeUnit: string; //大小单位 mb
    note: string; //说明
  },
  requestParams?: Object;//传参
  onRef: Function; //导入组件ref
}

interface State {
  modalTitle: string;
  visible: boolean;
  currentFile: any;
  loadding: boolean;
  clearTableDataFN: Function;
  recordId: string;
  rate: number;
  total: string | number;
  isSync: boolean;
}
const prefixStr = '';

const FileBox = ({
  prefix,
  downloadType,
  downTemplateMethod,
  downTemplateUrl = '',
  downTemplateFileName = '',
  downTemplateCode,
  callBakCurrentFile,
  maxSize,
  sizeUnit,
  note,
  accept,
  clearTableDataCallbak
}) => {
  const [tableData, setTableData] = useState([]);

  // 选择文件
  const selectFile = (req) => {
    console.log('req', req.file); //excel的基本信息
    //判断大小
    let sizeStatus = validationFileSize(req.file, maxSize);
    if (!sizeStatus.validaStatus) {
      message.error('超过最大限制' + maxSize);
      return false;
    }
    //校验文件类型
    let typeStatus = validationaccept(req.file, accept);
    if (!typeStatus) {
      message.error('仅支持' + accept + '文件');
      return false;
    }
    //更新文件
    setTableData([
      {
        fileName: req.file.name,
        fileSize: (req.file.size / sizeStatus.transformationRatio).toFixed(2),
        id: '1'
      }
    ]);
    callBakCurrentFile(req.file);
  };
  //删除
  const del = () => {
    if (tableData.length >= 1) {
      setTableData([]);
      callBakCurrentFile(null);
    }
  };

  //校验文件类型
  const validationaccept = (file, accept) => {
    const { name } = file;
    let reg = new RegExp('.(' + accept + ')$');
    return reg.test(name);
  };
  //校验文件大小
  const validationFileSize = (file, maxSize) => {
    const { size } = file;
    //获取转换比例，如果是kb 就是1，mb就是1024
    const transformationRatio =
      sizeUnit.toLocaleUpperCase() === 'KB' ? 1024 : 1024 * 1024;
    if (size > maxSize * transformationRatio) {
      message.error('文件不能超过' + maxSize + sizeUnit.toLocaleUpperCase());
      return {
        validaStatus: false
      };
    }
    return {
      validaStatus: true,
      transformationRatio
    };
  };

  //清空tableData
  const clearTableData = () => {
    setTableData([]);
    callBakCurrentFile(null);
  };

  useEffect(() => {
    clearTableDataCallbak(clearTableData);
  }, []);

  //下载模版
  const downFile = () => {
    commonExport({
      method: downTemplateMethod,
      url: prefixStr + downTemplateUrl,
      fileName: downTemplateFileName
    });
  };

  //下载本地模版
  const downLocalFile = () => {
    const downa = document.createElement('a');
    downa.href = window.location.origin + downTemplateUrl + `?time=${new Date().getTime()}`;
    downa.download = downTemplateFileName;
    downa.style.textDecoration = 'underline';
    document.body.appendChild(downa);
    downa.click();
    document.body.removeChild(downa);
  };

  const handleDownFile = () => {
    if (downloadType === 'templateCode') {
      commonExport({
        method: 'GET',
        // url: `/coordinator/el-fsm-service/api/tmpl/file/byTmplCode?tmplCode=${downTemplateCode}`,
        url: `${prefix}/com/import/${downTemplateCode}/tmpl`,
        fileName: downTemplateFileName,
      });
    } else if (downloadType === 'request') {
      downFile();
    } else if (downloadType === 'path') {
      downLocalFile();
    }
  }

  const column = [
    {
      title: '序号',
      dataIndex: 'key',
      render: (value, row, index) => <span>{index + 1}</span>
    },
    {
      title: '文件名称',
      dataIndex: 'fileName'
    },
    {
      title: '文件大小',
      dataIndex: 'fileSize',
      render: (value) => {
        return (
          <span>
            {value}
            {sizeUnit.toLocaleUpperCase()}
          </span>
        );
      }
    }
  ];
  return (
    <div className='el-import-table'>
      <div className='import-button-box'>
        <Upload
          accept='application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
          listType='text'
          multiple={false}
          customRequest={(req) => selectFile(req)}
          showUploadList={false}
        >
          <Button
            icon={<img src={iconAdd} style={{ marginRight: '4px' }}></img>}
            className='el-btn-default'
          >
            选择文件
          </Button>
        </Upload>
        <Button
          className='el-btn-default'
          style={{ marginLeft: '8px' }}
          onClick={handleDownFile}
          icon={<img src={iconDownload} style={{ marginRight: '4px' }}></img>}
        >
          模版下载
        </Button>
        <Popconfirm
          title='确认要删除吗？'
          okText='确认'
          cancelText='取消'
          onConfirm={del}
        >
          <Button
            className='el-btn-default'
            style={{ marginLeft: '8px' }}
            icon={<img src={iconDel} style={{ marginRight: '4px' }}></img>}
          >
            删除
          </Button>
        </Popconfirm>
        <span className='import-button-box-span'>{note}</span>
      </div>
      <Table
        size='small'
        columns={column}
        dataSource={tableData}
        pagination={{ hideOnSinglePage: true }}
        rowKey='id'
        bordered
      />
    </div>
  );
};

class ELImportExcel extends React.Component<Props, State> {
  xmlhhtp: any;
  static defaultProps = {
    prefix: '',
    importConfig: {
    },
    requestParams: {}
  };
  constructor(props) {
    super(props);
    this.state = {
      modalTitle: '文件导入',
      visible: false,
      currentFile: null,
      loadding: false,
      clearTableDataFN: null,
      recordId: null,
      rate: 0,
      total: 0,
      isSync: true
    };
  }

  callBakCurrentFile(file) {
    this.setState({
      currentFile: file
    });
  }

  componentDidMount() {
    if (this.props.onRef) {
      this.props.onRef(this);
    }
  }

  clearTableDataCallbak = (fn) => {
    this.setState({
      clearTableDataFN: fn
    });
  };

  openModal = () => {
    this.setState({
      visible: true
    });
  };

  closeModal = (isBackstage) => {
    if (isBackstage) {
      this.setState({
        visible: false
      });
    } else {
      const { clearTableDataFN } = this.state;
      this.xmlhhtp && this.xmlhhtp.abort();
      clearTableDataFN();
      this.setState({
        visible: false
      });
      this.handleRest();
      this.xmlhhtp = null;
    }

  };
  handleRest = () => {
    this.setState({
      loadding: false,
      recordId: null,
      rate: 0,
      isSync: true
    });
    const { clearTableDataFN } = this.state;
    clearTableDataFN();
    this.xmlhhtp && this.xmlhhtp.abort();
    this.xmlhhtp = null;
  }

  setLoadding = (params) => {
    this.setState({
      loadding: params
    });
  };

  //上传文件
  handleImport = () => {
    const { templateCode, prefix, requestParams: params } = this.props;
    const { mode, url, onSuccess, onFailed } = this.props.importConfig;
    const { currentFile } = this.state;

    let requestUrl = ''
    if (mode === 'templateCode') {
      if (!templateCode) {
        console.error('缺少templateCode参数');
        return;
      } else {
        requestUrl = `${prefix}/com/import/${templateCode}/data`;
      }

    } else if (mode === 'request') {
      if (!url) {
        console.error('缺少uploadConfig.url参数');
        return;
      } else {
        requestUrl = url;
      }
    } else {
      console.error('importConfig.mode参数不正确');
      return
    }

    //判断文件是否存在
    if (!currentFile) {
      message.error('请选择文件');
      return;
    }
    const formData = new FormData();
    formData.append('file', currentFile);

    if (Object.keys(params).length > 0) {
      if (!!params && Object.keys(params).length > 0) {
        Object.keys(params).forEach((key) => {
          formData.append(key, params[key]);
        });
      }
    }

    const xmlhttp = new XMLHttpRequest();
    this.xmlhhtp = xmlhttp;
    xmlhttp.timeout = 60000; //请求超时 60秒
    xmlhttp.open('POST', requestUrl);
    xmlhttp.setRequestHeader(
      'Authorization',
      `${window.localStorage.getItem('Authorization')}`
    );
    xmlhttp.onreadystatechange = async (e) => {
      //请求处理中
      if (xmlhttp.readyState === 3) {
        return;
      }
      //请求完成
      if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
        let response = JSON.parse(xmlhttp.response);
        console.log('responseresponse', response);
        if (response?.success) {
          const { sync, syncResult, asyncResult } = response.data;
          if (sync) {
            const { failRecords, numSuccess, total } = syncResult;
            ElNotification({
              type: 'info',
              message: `导入完成，总记录数${total}，导入成功${numSuccess}。错误描述见系统中心-模版管理-模版使用记录`,
              duration: 30
            });
            onSuccess && onSuccess(response);
            this.closeModal(false);
          } else {
            const { importId } = asyncResult;
            this.setState({
              recordId: importId,
              isSync: false
            });
            await this.queryRate(prefix, importId);
          }
        } else {
          ElNotification({
            type: 'error',
            message: response.msg || '导入失败',
            duration: 30
          });
          this.setLoadding(false);
        }
      } else if (xmlhttp.readyState === 4 && xmlhttp.status === 404) {
        let response = JSON.parse(xmlhttp.response);
        onFailed && onFailed(response);
        this.setLoadding(false);
      }
    };
    xmlhttp.ontimeout = (e) => {
      message.error('请求超时');
      xmlhttp.abort();
      this.setLoadding(false);
    };
    xmlhttp.send(formData);
    this.setLoadding(true);
  };
  queryRate = async (prefix, recordId) => {
    const res_info = await fetchImportRate(prefix, recordId);
    if (res_info?.success) {
      const { finish, total, count } = res_info.data;
      const rate = +Number(divide(count, total)).toFixed(2) * 100;
      this.setState({
        rate,
        total
      });
      if (!finish) {
        setTimeout(() => {
          this.queryRate(prefix, recordId);
        }, 2000);
      } else {
        this.setState({
          recordId,
          loadding: false
        });
      }
    } else {
      ElNotification({
        type: 'error',
        message: res_info.msg || res_info.data || '导入失败，请重试'
      });
      this.handleRest();
    }
  };

  handleGoToLogPage = () => {
    const { push } = this.props;
    this.closeModal(false);
    push('/sys/template/log');
  }

  fileBoxRender() {
    const { templateCode } = this.props;
    const { mode, requestMethod, url, fileName, } = this.props.downTemplateConfig;
    const { maxSize, sizeUnit, note, accept } = this.props.importConfig;
    return <FileBox
      {...omit(['downTemplateConfig', 'importConfig'], this.props)}
      downloadType={mode}
      downTemplateMethod={requestMethod}
      downTemplateUrl={url}
      downTemplateFileName={fileName}
      downTemplateCode={templateCode}
      clearTableDataCallbak={(clearTableDataCallbak) =>
        this.clearTableDataCallbak(clearTableDataCallbak)
      }
      callBakCurrentFile={(file) => this.callBakCurrentFile(file)}
      maxSize={maxSize}
      sizeUnit={sizeUnit}
      note={note}
      accept={accept}
    />
  }

  render() {
    const { modalTitle, visible, loadding, recordId, total, rate, isSync } = this.state;
    return (
      <Modal
        title={modalTitle}
        visible={visible}
        closable={false}
        width='550px'
        onCancel={this.closeModal}
        maskClosable={false}
        // bodyStyle={{ padding: '0px' }}
        className='el-import-modal'
        footer={
          getModalFooter({
            isSync,
            loadding: loadding,
            recordId,
            closeModal: this.closeModal,
            handleImport: this.handleImport,
            handleRest: this.handleRest
          })
          // <div>
          //   <Button icon={<ClosecircleBlack />} onClick={this.closeModal}>
          //     取消
          //   </Button>
          //   <Button
          //     type='primary'
          //     icon={<CheckcircleBlack />}
          //     onClick={this.handleImport}
          //     loading={loadding}
          //   >
          //     上传
          //   </Button>
          // </div>
        }
      >
        {
          loadding ?
            <div>
              {
                total > 0 ? <><span>正在导入{total}条记录...</span>
                  <Progress percent={rate} /></> : (<span>正在导入</span>)
              }
            </div>
            : recordId ?
              <div>
                <span>导入已成功</span>
                <br />
                <span>您可在<Button key='button' type='link' onClick={() => { this.handleGoToLogPage() }}>模板使用记录</Button>查询历史导入记录</span>
              </div>
              : <div style={{ margin: -24 }}>
                {/* <div>导入大量数据时需要花费一些时间，确定确认是否继续？</div>
                                <br />
                                <div>您可在<Button key='button' type='link' onClick={() => { this.handleGoToLogPage() }}>模板使用记录</Button>查询历史导入记录</div> */}
                {this.fileBoxRender()}
              </div>
        }

      </Modal>
    );
  }
}

export default ELImportExcel;
